package cn.edu.xaut.mybatisers.mall.ServiceImp;

import cn.edu.xaut.mybatisers.mall.Dao.BillDao;
import cn.edu.xaut.mybatisers.mall.Entity.Bill;
import cn.edu.xaut.mybatisers.mall.Entity.Commodity;
import cn.edu.xaut.mybatisers.mall.Entity.OrderOneByOne;
import cn.edu.xaut.mybatisers.mall.Exception.ExceptionEntity.BillStatusException;
import cn.edu.xaut.mybatisers.mall.Service.BillService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Service
@SuppressWarnings("all")
public class BillServiceImp implements BillService {
    @Autowired
    BillDao billDao;

    @Autowired
    RabbitTemplate rabbitTemplate;

    @Override
    public ArrayList<Bill> getBillByOrderNumber(Bill bill) throws SQLException {
        return billDao.selectByOrderNumber(bill.getOrder_number());
    }

    @Override
    public String createOrder(Bill bill) throws SQLException {
        String orderNumber = generateUniqueNumber(bill.getConsumer_id());
        bill.setSubmitTime(new Timestamp(new Date().getTime()));
        bill.setOrder_number(orderNumber);
        billDao.createOrder(bill);
        /**
         *  起一个定时任务将订单超过时未支付就取消
         *  传递参数是订单号
         *  时间是10分钟
         * **/
        if(System.getProperty("delayTask") != null) {
            rabbitTemplate.convertAndSend(
                    "customerExchange",
                    "billDelayQueue",
                    orderNumber,
                    message -> {
                        message.getMessageProperties().setHeader("x-delay", 60000);
                        return message;
                    }
            );
            System.out.println("发送消息[添加定时任务取消超时订单]: " + ">>>>>>>" + LocalDateTime.now());
        }

        return orderNumber;
    }

    @ApiOperation("生成唯一订单号")
    @Override
    public String generateUniqueNumber(int customerId) {
        final String alphabet = "ABCDEFGHIZKLMNOPQRSTUVWXYZ";
        //时间（精确到毫秒）
        DateTimeFormatter ofPattern = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
        String localDate = LocalDateTime.now().format(ofPattern);
        //3位随机字母
        String randomChao = new String();
        for (int i=0; i<3; i++)
            randomChao += alphabet.charAt((int)(Math.random() * 26));
        //5位用户id
        int subStrLength = 5;
        String sUserId = String.valueOf(customerId);
        int length = sUserId.length();
        String str;
        if (length >= subStrLength) {
            str = sUserId.substring(length - subStrLength, length);
        } else {
            str = String.format("%0" + subStrLength + "d", customerId);
        }
        String orderNum = localDate + randomChao + str;
        System.out.println(orderNum);
        return orderNum;
    }

    @Override
    public Boolean alterBill(Bill bill) throws SQLException, BillStatusException {
        int status = billDao.selectByOrderNumber(bill.getOrder_number()).get(0).getBillStatus();
        if ((status == 3 || status == 4 || status == 5 || status == 6) && (bill.getAddress_city() != null ||
                bill.getAddress_county() != null || bill.getAddress_location() != null || bill.getAddress_province() != null
                || bill.getTeleNumber() != null || bill.getTotalPrice() > 0)
        )
            throw new BillStatusException("订单状态不允许修改");
        billDao.alterOrder(bill);
        return true;
    }

    @Override
    public PageInfo<Bill> getAllBillByPage(int consumer_id, int pageNum, int pageSize) throws SQLException {
        PageHelper.startPage(pageNum, pageSize);
        ArrayList<Bill> allBills = billDao.getAllOrder(consumer_id);
        return new PageInfo<>(allBills);
    }

    @Override
    public PageInfo<Bill> findBillByStatus(int consumer_id, int billStatus,  int pageNum, int pageSize) throws SQLException {
        PageHelper.startPage(pageNum, pageSize);
        return new PageInfo<>(billDao.findBillByStatus(consumer_id, billStatus));
    }

    @Override
    public Boolean addCommodityToOrder(List<OrderOneByOne> orderOneByOnes) throws SQLException {
        billDao.addCommodityToOrder(orderOneByOnes);
        return true;
    }

    @Override
    public List<HashMap<String, Object>> getCommodities(String orderNumber) throws SQLException {
        return billDao.getCommodities(orderNumber);
    }

    @Override
    public Map<String, Object> submitBill(String orderNumber) throws SQLException {
        ArrayList<Commodity> commodities = billDao.getCommodities1(orderNumber);
        HashMap<Integer, HashMap> orderOneByOnes = billDao.selectOrderObOByOrderNumber(orderNumber);
        Map<String, Object> return_data = new HashMap<>();
        int remainNumber =0;
        for (Commodity commodity : commodities) {
            System.out.println(commodity.getRepertory_number());
            System.out.println(orderOneByOnes.get(commodity.getId()).get("buy_number"));
            remainNumber = commodity.getRepertory_number() - (Integer) orderOneByOnes.get(commodity.getId()).get("buy_number");
            if (remainNumber < 0) {
                return_data.put("result", false);
                return_data.put("lackCommodity_id", commodity.getId());
                return_data.put("lackCommodity_name", commodity.getName());
                return return_data;
            } else
                commodity.setRepertory_number(remainNumber);
        }
        billDao.alterCommodityRepertoryNumber(commodities);
        Bill bill = new Bill();
        bill.setBillStatus(2);
        billDao.alterOrder(bill);
        return_data.put("result", true);
        return return_data;
    }

    @Override
    public int deleteOrder(Bill bill) throws SQLException {
        return billDao.deleteOrder(bill);
    }

    @Override
    public boolean comment(OrderOneByOne orderOneByOne) throws SQLException {
        billDao.comment(orderOneByOne);
        return true;
    }

    @Override
    public boolean deleteComment(OrderOneByOne orderOneByOne) throws SQLException {
        orderOneByOne.setEvaluate(null);
        billDao.comment(orderOneByOne);
        return true;
    }
}
